#pragma once

// ==================包含头文件====================
#include <array>
#include <cstdio>// 标准IO支持
#include <project_config.h>
#include <stm32f4xx_hal.h>
// ==================包含头文件====================
#include "etl/circular_buffer.h"

#include <span>

namespace hal::detail_usart
{
    /**
     * 串口管理类，后续可以很轻松地扩充为模板类，来兼容所有串口，这里就串口1比较常用，干脆用它代替
     */
    class USARTManager {
        static constexpr size_t RX_BUF_SIZE = 256;
        static constexpr size_t CIRC_BUF_SIZE = 512;

    public:
        static void init(uint32_t baud_rate = 115200)
        {
            // 1. 启用硬件时钟
            __HAL_RCC_DMA2_CLK_ENABLE();
            __HAL_RCC_USART1_CLK_ENABLE();
            __HAL_RCC_GPIOA_CLK_ENABLE();

            // 2. 配置GPIO (PA9=TX, PA10=RX)
            GPIO_InitTypeDef gpio = {
                .Pin = GPIO_PIN_9 | GPIO_PIN_10,
                .Mode = GPIO_MODE_AF_PP,
                .Pull = GPIO_NOPULL,
                .Speed = GPIO_SPEED_FREQ_HIGH,
                .Alternate = GPIO_AF7_USART1
            };
            HAL_GPIO_Init(GPIOA, &gpio);

            // 3. 配置UART
            huart_.Instance = USART1;
            huart_.Init = {
                .BaudRate = baud_rate,
                .WordLength = UART_WORDLENGTH_8B,
                .StopBits = UART_STOPBITS_1,
                .Parity = UART_PARITY_NONE,
                .Mode = UART_MODE_TX_RX,
                .HwFlowCtl = UART_HWCONTROL_NONE,
                .OverSampling = UART_OVERSAMPLING_16
            };
            HAL_UART_Init(&huart_);

            // 4. 配置DMA
            hdma_tx_.Instance = DMA2_Stream7;
            hdma_tx_.Init.Channel = DMA_CHANNEL_4;
            hdma_tx_.Init.Direction = DMA_MEMORY_TO_PERIPH;
            hdma_tx_.Init.PeriphInc = DMA_PINC_DISABLE;
            hdma_tx_.Init.MemInc = DMA_MINC_ENABLE;
            hdma_tx_.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
            hdma_tx_.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
            hdma_tx_.Init.Mode = DMA_NORMAL;
            hdma_tx_.Init.Priority = DMA_PRIORITY_LOW;
            hdma_tx_.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
            HAL_DMA_Init(&hdma_tx_);
            __HAL_LINKDMA(&huart_, hdmatx, hdma_tx_);


            hdma_rx_.Instance = DMA2_Stream2;
            hdma_rx_.Init = {
                .Channel = DMA_CHANNEL_4,
                .Direction = DMA_PERIPH_TO_MEMORY,
                .PeriphInc = DMA_PINC_DISABLE,
                .MemInc = DMA_MINC_ENABLE,
                .PeriphDataAlignment = DMA_PDATAALIGN_BYTE,
                .MemDataAlignment = DMA_MDATAALIGN_BYTE,
                .Mode = DMA_CIRCULAR, // 循环模式自动处理溢界
                .Priority = DMA_PRIORITY_HIGH,
                .FIFOMode = DMA_FIFOMODE_DISABLE
            };
            HAL_DMA_Init(&hdma_rx_);
            __HAL_LINKDMA(&huart_, hdmarx, hdma_rx_);

            // 5. 启用空闲中断
            __HAL_UART_ENABLE_IT(&huart_, UART_IT_IDLE);

            HAL_NVIC_SetPriority(USART1_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(USART1_IRQn);

            // 6. 启动DMA接收
            HAL_UART_Receive_DMA(&huart_, dma_rx_buffer_.data(), dma_rx_buffer_.size());
        }

        /**
         * 处理字符串
         * @tparam is_process_byte 是否添加但字符处理函数
         * @tparam is_process_string 是否添加字符串处理函数
         * @tparam max_size 单次处理的字符串大小
         * @param process_byte 字符处理函数
         * @param process_string 字符串处理函数
         * @note 处理字符串，如回显处理
         *      hal::usart::process_string<false,true>(nullptr,[]( uint8_t *str, size_t size) {
                    hal::usart::send(str, size);
                });
         */
        template<bool is_process_byte = false, bool is_process_string = false, std::size_t max_size = RX_BUF_SIZE>
        static void process_string(void (*process_byte)(uint8_t data) = nullptr,
                                   void (*process_string)(uint8_t *str, size_t size) = nullptr)
        {
            if (rx_circ_buf_.empty()) return;

            std::array<uint8_t, max_size> tempBuffer{};
            for (std::size_t i = 0; i < max_size - 1; ++i) {
                const uint8_t c = rx_circ_buf_.front();
                rx_circ_buf_.pop();
                tempBuffer[i] = c;
                if constexpr (is_process_byte) process_byte(c);
                if (tempBuffer[i] == '\r' && tempBuffer[i + 1] == '\n' || rx_circ_buf_.empty()) {
                    if constexpr (is_process_string) process_string(reinterpret_cast<uint8_t *>(tempBuffer.data()),
                                                                    i + 1);
                    return;
                }
            }
        }


        // 回显函数
        static void echo()
        {
            if (get_receive_event()) {
                auto it = dma_rx_buffer_.begin();
                for (const auto end = dma_rx_buffer_.end() - 1; it != end; ++it) {
                    if (*it == '\r' && *(it + 1) == '\n') {
                        const size_t packet_length = std::distance(dma_rx_buffer_.begin(), it) + 2;
                        send(dma_rx_buffer_.data(), packet_length);
                        return;
                    }
                }
            }
        }

        static bool get_receive_event()
        {
            const bool ret = new_data_available_;
            new_data_available_ = false;
            return ret;
        }

        // 发送数据接口(暂时不知道为什么要减一）
        template<typename T, std::size_t size>
        static void send(std::array<T, size> &data)
        {
            HAL_UART_Transmit_DMA(&huart_, data.data(), data.size());
        }

        template<typename T>
        static void send(T data, const size_t size)
        {
            HAL_UART_Transmit_DMA(&huart_, reinterpret_cast<uint8_t *>(data), size);
        }

        template<typename T>
        static void send(std::span<const T> data)
        {
            HAL_UART_Transmit_DMA(&huart_,
                                  reinterpret_cast<const uint8_t *>(data.data()),
                                  data.size_bytes());
        }


        static DMA_HandleTypeDef *get_dma_rx_handle()
        {
            return &hdma_rx_;
        }

        static DMA_HandleTypeDef *get_dma_tx_handle()
        {
            return &hdma_tx_;
        }

        static UART_HandleTypeDef *get_uart_handle() { return &huart_; }

        // 处理空闲中断的静态方法
        static void handle_idle_irq()
        {
            if (__HAL_UART_GET_FLAG(&huart_, UART_FLAG_IDLE) != RESET) {
                __HAL_UART_CLEAR_IDLEFLAG(&huart_);

                // 停止DMA传输
                HAL_UART_DMAStop(&huart_);


                // 计算接收到的数据长度
                const auto dma_pos = RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(&hdma_rx_);

                // 将数据转入循环缓冲区
                for (size_t i = 0; i < dma_pos; ++i) {
                    // 安全检查：避免缓冲区溢出
                    if (!rx_circ_buf_.full()) {
                        rx_circ_buf_.push(dma_rx_buffer_[i]);
                    }
                }

                new_data_available_ = true;
                // 重新启动DMA接收
                HAL_UART_Receive_DMA(&huart_, dma_rx_buffer_.data(), dma_rx_buffer_.size());
            }
        }

    private:
        // DMA 接收缓冲区 - 内存对齐提升性能
        alignas(4) static inline std::array<uint8_t, RX_BUF_SIZE> dma_rx_buffer_{};

        // ETL 循环缓冲区 (双重缓冲策略)
        static inline etl::circular_buffer<uint8_t, CIRC_BUF_SIZE> rx_circ_buf_{};

        // 标记新数据到达
        static inline volatile bool new_data_available_ = false;


        // 硬件句柄 (静态单例)
        static inline UART_HandleTypeDef huart_{};
        static inline DMA_HandleTypeDef hdma_rx_{};
        static inline DMA_HandleTypeDef hdma_tx_{};
    };
} // namespace bsp


namespace hal
{

    using usart = detail_usart::USARTManager;
}

// ================== 模块内部实现 ==================
